use super::label_selector::{set_matcher::SetMatcher, SelectorMatcher, SelectorMatchers};
use crate::config::app_error::AppResult;
use crate::extension::index::index::query::query::query_factory;
use crate::extension::index::index::query::query::query_factory::Query;
use crate::extension::index::selector::label_selector::equality_matcher::EqualityMatcher;
use ordermap::OrderSet;
use std::fmt::{Display, Formatter};

#[derive(Clone, Debug)]
pub enum Operator {
    // "=", 3
    Equals(String, usize),
    // "=(", 2
    IN(String, usize),
    // "!=", 1
    NotEquals(String, usize),
    // "!", 0
    NotExist(String, usize),
    // "", Integer.MAX_VALUE
    Exist(String, usize),
}

impl Display for Operator {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        match self {
            Operator::Equals(str, size) => write!(f, "{} {}", str, size),
            Operator::IN(str, size) => write!(f, "{} {}", str, size),
            Operator::NotEquals(str, size) => write!(f, "{} {}", str, size),
            Operator::NotExist(str, size) => write!(f, "{} {}", str, size),
            Operator::Exist(str, size) => write!(f, "{} {}", str, size),
        }
    }
}

// protected boolean preFlightCheck(String selector, int minLength) {
//     return selector != null && selector.length() >= minLength;
// }
trait Converter {
    fn convert(&self, selector: &String) -> Option<SelectorCriteria>;
}
pub struct SelectorCriteria {
    pub key: String,
    operator: Operator,
    pub values: OrderSet<String>,
}

fn operator_list() -> Vec<Operator> {
    let mut v = Vec::new();
    v.push(Operator::Equals("=".to_string(), 0));
    v.push(Operator::IN("=(".to_string(), 1));
    v.push(Operator::NotEquals("!=".to_string(), 2));
    v.push(Operator::Exist("!".to_string(), 3));
    v.push(Operator::Exist("".to_string(), 10));
    v
}
pub fn convert_selector(selector: String) -> Option<SelectorCriteria> {
    operator_list()
        .iter()
        .map(|operator| operator.convert(&selector))
        .find_map(|it| it)
        .or(None)
}

pub fn convert_label(criteria: SelectorCriteria) -> SelectorMatchers {
    match criteria.operator {
        Operator::Equals(_, _) => SelectorMatchers::EqualityMatcher(EqualityMatcher::equal(
            criteria.key.clone(),
            get_single_value(&criteria),
        )),
        Operator::IN(_, _) => {
            SelectorMatchers::SetMatcher(SetMatcher::in_values(criteria.key, criteria.values))
        }
        Operator::NotEquals(_, _) => SelectorMatchers::EqualityMatcher(EqualityMatcher::not_equal(
            criteria.key.clone(),
            get_single_value(&criteria),
        )),
        Operator::NotExist(_, _) => {
            SelectorMatchers::SetMatcher(SetMatcher::not_exists(criteria.key.clone()))
        }
        Operator::Exist(_, _) => {
            SelectorMatchers::SetMatcher(SetMatcher::exists(criteria.key.clone()))
        }
    }
}

pub fn convert_field(criteria: SelectorCriteria) -> AppResult<Query> {
    let mut key = criteria.key.clone();
    if key == "name" {
        key = "metadata.name".to_string();
    }
    match criteria.operator {
        Operator::Equals(_, _) => Ok(Query::Equal(query_factory::equal(
            &key,
            get_single_value(&criteria),
        ))),
        Operator::IN(_, _) => Ok(Query::In(query_factory::in_query(key, criteria.values))),
        Operator::NotEquals(_, _) => Ok(Query::NotEqual(query_factory::not_equal(
            criteria.key.clone(),
            get_single_value(&criteria),
        ))),
        _ => Err(anyhow::anyhow!("Unsupported operator: {}", criteria.operator).into()),
    }
}

fn get_single_value(criteria: &SelectorCriteria) -> String {
    if criteria.values.is_empty() {
        "".to_string()
    } else {
        criteria.values.iter().next().unwrap().to_string()
    }
}

fn pre_flight_check(selector: &String, min_length: usize) -> bool {
    !selector.is_empty() && selector.len() >= min_length
}

// 为 Operator 枚举实现 Converter trait
impl Converter for Operator {
    fn convert(&self, selector: &String) -> Option<SelectorCriteria> {
        match self {
            Operator::Equals(operator, order) => {
                if pre_flight_check(selector, 3) {
                    if selector.len() >= *order && selector.contains(operator) {
                        let parts: Vec<&str> = selector.splitn(2, operator).collect();
                        if let Some(value) = parts.get(1) {
                            return Some(SelectorCriteria {
                                key: parts[0].to_string(),
                                operator: Operator::Equals("=".to_string(), 3),
                                values: [value.to_string()].iter().cloned().collect(),
                            });
                        }
                    }
                }
                None
            }
            Operator::IN(operator, order) => {
                if pre_flight_check(&selector, 5) {
                    if selector.contains(operator) && selector.ends_with(")") {
                        //=(1,2,3)
                        let parts: Vec<&str> = selector.splitn(2, operator).collect();
                        if let Some(value) = parts.get(1) {
                            let value_str = &value[0..value.len() - 1];
                            let values = value_str.split(",").map(|t| t.to_string()).collect();
                            return Some(SelectorCriteria {
                                key: parts[0].to_string(),
                                operator: Operator::IN(operator.clone(), *order),
                                values,
                            });
                        }
                    }
                }
                None
            }
            Operator::NotEquals(operator, order) => {
                if pre_flight_check(&selector, 4) {
                    if selector.len() >= *order && selector.contains(operator) {
                        let parts: Vec<&str> = selector.splitn(2, operator).collect();
                        if let Some(value) = parts.get(1) {
                            return Some(SelectorCriteria {
                                key: parts[0].to_string(),
                                operator: Operator::NotEquals("!=".to_string(), 1),
                                values: [value.to_string()].iter().cloned().collect(),
                            });
                        }
                    }
                }
                None
            }
            Operator::NotExist(operator, order) => {
                if pre_flight_check(&selector, 2) {
                    if selector.starts_with(operator) {
                        let key = &selector[1..];
                        return Some(SelectorCriteria {
                            key: key.to_string(),
                            operator: Operator::NotExist("!".to_string(), *order),
                            values: OrderSet::new(),
                        });
                    }
                }
                None
            }
            Operator::Exist(operator, order) => {
                if pre_flight_check(&selector, 1) {
                    if selector.starts_with(operator) {
                        return Some(SelectorCriteria {
                            key: selector.clone(),
                            operator: Operator::Exist(operator.to_string(), *order),
                            values: OrderSet::new(),
                        });
                    }
                }
                None
            }
        }
    }
}
